package com.jxy.homepage.security.jwt.security;

import com.jxy.homepage.security.jwt.*;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.util.Arrays;
import java.util.Collections;

/**
 * WebSecurityConfig
 *
 * @author Jxy
 * @date 2022/1/6
 * @Description Security
 */
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
    private final JwtAuthenticationEntryPoint authentication;
    private final JwtTokenUtils jwtTokenUtils;
    private final JwtSecurityProperties jwtSecurityProperties;

    public static final String[] AUTH_WHITELIST = {
            "/api//auth/login",
            "/error/**",
            "api/cv/**"
    };

    public WebSecurityConfig(JwtAccessDeniedHandler jwtAccessDeniedHandler,
                             JwtAuthenticationEntryPoint authentication,
                             JwtTokenUtils jwtTokenUtils, JwtSecurityProperties jwtSecurityProperties) {
        this.jwtAccessDeniedHandler = jwtAccessDeniedHandler;
        this.authentication = authentication;
        this.jwtTokenUtils = jwtTokenUtils;
        this.jwtSecurityProperties = jwtSecurityProperties;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

//        http.cors().configurationSource(corsConfigurationSource())
        http
                .csrf().disable()
                // 授权异常
                .exceptionHandling()
                .authenticationEntryPoint(authentication)
                .accessDeniedHandler(jwtAccessDeniedHandler)
                // 防止iframe造成跨域
                .and()
                .headers()
                .frameOptions()
                .disable()

                // 不创建会话
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

                .and()
                .authorizeRequests()
                .antMatchers("/druid/**").permitAll()
                .antMatchers(AUTH_WHITELIST).permitAll()
                // 其他请求要认证
                .anyRequest().authenticated();

        // 禁用缓存
        http.headers().cacheControl();

        // 添加JWT filter
        http.apply(new TokenConfigurer(jwtTokenUtils, jwtSecurityProperties));

    }

    /**
     * 跨域配置
     */
//    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
//    @Bean
//    public CorsFilter corsFilter() {
//        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//
//        CorsConfiguration corsConfiguration = new CorsConfiguration();
//        corsConfiguration.addAllowedOrigin("*");
//        corsConfiguration.addAllowedHeader("*");
//        corsConfiguration.addAllowedMethod("*");
//        corsConfiguration.setAllowCredentials(true);
//
//        source.registerCorsConfiguration("/**", corsConfiguration);
//        return new CorsFilter(source);
//    }

    public class TokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

        private final JwtTokenUtils jwtTokenUtils;
        private final JwtSecurityProperties jwtSecurityProperties;

        public TokenConfigurer(JwtTokenUtils jwtTokenUtils, JwtSecurityProperties jwtSecurityProperties) {

            this.jwtTokenUtils = jwtTokenUtils;
            this.jwtSecurityProperties = jwtSecurityProperties;
        }

        @Override
        public void configure(HttpSecurity http) {
            JwtAuthenticationTokenFilter customFilter = new JwtAuthenticationTokenFilter(jwtTokenUtils, jwtSecurityProperties);
            http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
        }
    }
}
